package org.rcgwt.client.ui.validator.impl;

import java.util.Map;

import org.rcgwt.client.ui.validator.ICharacterSets;
import org.rcgwt.client.ui.validator.IChecker;
import org.rcgwt.client.ui.validator.IClientValidatorContext;
import org.rcgwt.client.ui.validator.messages.Severity;
import org.rcgwt.client.util.Pattern;

/**
 * A Checker which checks a INSEE number structure (like S YY MM DD CIT ORD KE)
 * and the validity of the control key
 * 
 * @author Elian ORIOU
 * 
 */

public class INSEEChecker implements IChecker {

	/* INSEE CHECKER PATTERNS */
	private static final String sex_pattern = "^[1-2]";
	private static final String year_pattern = "[0-9]{2}";
	private static final String month_pattern = "[0-1][0-9]";
	private static final String dept_pattern = "([0-9]{2}|2A|2B)";
	private static final String city_pattern = "[0-9]{3}";
	private static final String birth_order = "[0-9]{3}";
	private static final String key_pattern = "[0-9]{2}$";

	private final Pattern INSEE_PATTERN;

	private static final String MY_PATTERN = ICharacterSets.NUM_SET;

	public INSEEChecker(Map<String, String> parameters) {
		INSEE_PATTERN = Pattern.compile(sex_pattern + year_pattern
				+ month_pattern + dept_pattern + city_pattern + birth_order
				+ key_pattern);
	}

	@Override
	public boolean check(IClientValidatorContext context, String s) {

		/* If the key is structured as S YY MM DD CIT ORD KE */
		if (INSEE_PATTERN.matches(s)) {
			// Key check control (97 - insee number % 97)
			String insee = "";
			for (int i = 0; i < s.length() - 2; i++) {
				String ch = String.valueOf(s.charAt(i));
				if (MY_PATTERN.indexOf(ch) != -1) {
					/*
					 * The first 13 characters are analyzed, for the
					 * determination of the control key
					 */
					insee += ch;
				} else {
					/*
					 * Alphabetic characters are replaced by a zero (for the
					 * Corsica Exception : 2A | 2B)
					 */
					insee += "0";
				}
			}
			/* The control key (the last 2 characters) */
			int key = Integer.parseInt("" + s.charAt(s.length() - 2)
					+ s.charAt(s.length() - 1));
			/* Insee Number body parsing (without the control key) */
			Long insee_n = Long.parseLong(insee);

			if ((97 - (insee_n % 97)) == key) {
				/* VALID key */
				return true;
			} else {
				context.addMessage(context.getMessagesProvider()
						.ControlErrorShort(), context.getMessagesProvider()
						.ControlError(), Severity.ERROR);
				return false;
			}
		} else {
			context.addMessage(context.getMessagesProvider()
					.StructureErrorShort(), context.getMessagesProvider()
					.StructureError(), Severity.ERROR);
			return false;
		}
	}
}
